home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGBLER / HERCBIOS.LZH / GCHAR.ASM next >
Assembly Source File  |  1980-01-01  |  19KB  |  531 lines

  1.  
  2. ;********************************************************************
  3. ;*
  4. ;*     GRAPHIC CHARACTER HANDLING
  5. ;*
  6. ;*             Dave Tutelman - 8/86
  7. ;*
  8. ;*-------------------------------------------------------------------
  9. ;*
  10. ;*     Fn 6    Scroll up - not yet implemented
  11. ;*     Fn 7    Scroll down - not yet implemented
  12. ;*     Fn 9    Write character with attribute
  13. ;*     Fn 10   Write character normal
  14. ;*     Fn 14   Write character Teletypewriter style
  15. ;*
  16. ;*     Also includes subroutines to:
  17. ;*     get_address     convert page/row/col to display address
  18. ;*     do_char         write a character to an address on display
  19. ;*     do_attrib       change a display address to some attribute
  20. ;*     full_screen_scroll      used by Fn 14, when it needs to scroll
  21. ;*     flash           momentarily flash to reverse video and back
  22. ;*
  23. ;********************************************************************
  24. ;
  25. INCLUDE        hercbios.h
  26.  
  27. ;-----------------------------------------------
  28. extrn  exit_herc_bios:near
  29. public writechar,scroll_up,scroll_down,tty
  30. public scr_start,scr_length,num_rows
  31. ;------------------------------------
  32. cseg   segment public
  33.        assume  cs:cseg,ds:bios_data
  34. ;
  35.  
  36. ;**************************************************************
  37. ;*
  38. ;*     FUNCTION 6 & 7 - SCROLL UP & DOWN
  39. ;*     (Placeholder only - not yet implemented)
  40. ;*
  41. ;*     AL = Number of rows to scroll (if 0, blank scroll area)
  42. ;*     BH = Fill attribute (we ignore, since writechar destroys old attrib)
  43. ;*     CX = Upper left corner      (CH=row, CL=col)
  44. ;*     DX = Lower right corner     (DH=row, DL=col)
  45. ;*
  46. ;****************************************************************
  47. ;
  48. scroll_up:
  49. scroll_down:
  50. ;
  51.        jmp     exit_herc_bios
  52. page
  53. ;********************************************************************
  54. ;*
  55. ;*     FUNCTION 9 & 10 - WRITE A CHARACTER AT CURRENT CURSOR
  56. ;*
  57. ;*     AL = character code to be written
  58. ;*     AH = 9 (write char with attribute) or 10 (write char normal)
  59. ;*     BL = new attribute (limited selection in graphics mode)
  60. ;*     BH = display page number
  61. ;*     CX = count of how many characters to write
  62. ;*
  63. ;********************************************************************
  64. ;
  65. writechar:
  66. ;                      ; Get the address corresponding to cursor[page]
  67.        push    bx
  68.        mov     bl,bh           ; page to BX
  69.        xor     bh,bh
  70.        shl     bx,1            ; *2 for word pointer
  71.        mov     dx,curs_pos[bx] ; appropriate cursor position to DX
  72.        pop     bx
  73.        call    get_address     ; get display address in DI
  74. ;
  75. wrchar_loop:
  76. ;                      ; Write a character to that address
  77.        call    do_char         ; arguments set up already
  78. ;
  79. ;                      ; If function 9, modify the character's attributes
  80.        cmp     ah,9            ; Function 9?
  81.        jne     no_attrib       ; no, don't do attributes
  82.        call    do_attrib       ; yes, and arguments already set up
  83. no_attrib:
  84. ;
  85.        inc     di              ; move to next position, without moving
  86.                                ;    the official cursor
  87.        loop    wrchar_loop     ; continue until CX count exhausted
  88.        jmp     exit_herc_bios
  89. page
  90. ;*****************************************************************
  91. ;*
  92. ;*     FUNCTION 14 - TELETYPEWRITER-STYLE CHARACTER WRITE
  93. ;*
  94. ;*     AL = Character to be written
  95. ;*
  96. ;******************************************************************
  97. ;
  98. tty:
  99.        assume  ds:bios_data
  100.        mov     bl,active_page  ; active page to BX
  101.        xor     bh,bh
  102.        mov     dx,curs_pos[bx] ; get cursor for active page
  103.        push    bx
  104.        mov     bh,bl           ; move page to BH
  105.        call    get_address     ; address of character to DI
  106.        pop     bx
  107. ;
  108. ;                      ; process the character
  109. ;                      ; check if CR
  110.        cmp     al,13           ; carriage return?
  111.        jne     not_cr
  112.        mov     dl,0            ; go to first column
  113.        jmp     fix_curs
  114. ;                      ; check if LF
  115. not_cr:        cmp     al,10           ; line feed?
  116.        jne     not_lf
  117.        inc     dh              ; next line
  118.        jmp     fix_curs
  119. ;                      ; check if BS
  120. not_lf:        cmp     al,8            ; backspace?
  121.        jne     not_bs
  122.        cmp     dl,0            ; already first column?
  123.        je      fix_curs        ; yup. do nothing
  124.        dec     dl              ; nope. move cursor left one
  125.        dec     di              ; also move address pointer left one
  126.        mov     al,32           ; set character to space
  127.        call    do_char         ; and write the space, but don't move
  128.        jmp     fix_curs
  129. ;                      ; check if BEL
  130. not_bs:        cmp     al,7            ; bell character?
  131.        jne     not_bl
  132.        pop     es              ; restore registers
  133.        pop     di
  134.        pop     si
  135.        pop     dx
  136.        pop     cx
  137.        pop     bx
  138.        pop     ds
  139.        jmp     vid_bios        ; ... and use the normal BIOS to ring the bell
  140. ;      call    flash           ; can't do BEL standard. Blink display instead
  141. ;      jmp     fix_curs
  142. ;                      ; ordinary printing character, so display it
  143. not_bl:        call    do_char         ; write it to screen
  144.        inc     dl              ; cursor one to the right
  145. ;
  146. ;                      ; now look at the cursor, do what's necessary to
  147. ;                      ; fix it up, and save it away.
  148. fix_curs:
  149.        cmp     dl,89           ; beyond last column?
  150.        jle     chk_scroll      ; not yet
  151.        xor     dl,dl           ; yes. do a CR
  152.        inc     dh              ; ... and a LF
  153. chk_scroll:
  154.        cmp     dh,cs:num_rows  ; now see if we're beyond last row?
  155.        jl      exit_tty        ; not yet
  156.        call    full_screen_scroll
  157.                                ; yes. Scroll the screen up one
  158.        dec     dh              ; ... and scroll cursor, too.
  159.        jmp     chk_scroll
  160. ;
  161. exit_tty:
  162.        mov     curs_pos[bx],dx ; save cursor position
  163.        jmp     exit_herc_bios
  164. page
  165. ;--------------------------------------------------------------------
  166. ;
  167. ;      GET_ADDRESS  SUBROUTINE
  168. ;
  169. ;      BH = display page
  170. ;      DX = cursor position (DH=row, DL=col)
  171. ;
  172. ;      returns:
  173. ;      DI = displacement of top row of pixels
  174. ;
  175. ;--------------------------------------------------------------------
  176. ;
  177. get_address:
  178.        push    cx              ; save it
  179.  
  180. ;                      ; compute display address from cursor_pos
  181.        mov     cl,dh           ; get row # in cx
  182.        xor     ch,ch
  183.        shl     cx,1            ; begin fast multiply by 90 (1011010 B)
  184.        mov     di,cx
  185.        shl     cx,1
  186.        shl     cx,1
  187.        add     di,cx
  188.        shl     cx,1
  189.        add     di,cx
  190.        shl     cx,1
  191.        shl     cx,1
  192.        add     di,cx           ; end fast multiply by 90
  193.        mov     cx,di           ; copy answer back to cx
  194.        shl     di,1            ; *2 for ibm graphics mode
  195.        cmp     video_mode,herc_mode
  196.        jne     ibm_ad          ; not herc mode
  197.        add     di,cx           ; *3 for herc mode
  198. ibm_ad:        xor     ch,ch           ; columns in CX
  199.        mov     cl,dl
  200.        add     di,cx           ; add in col. address in DI
  201.        cmp     bh,0            ; if page 1, set high-order bit of address
  202.        je      pg0
  203.        or      di,8000H
  204. pg0:
  205. ;                      ; address now in DI
  206. ;
  207.        pop     cx              ; restore it
  208.        ret
  209. page
  210. ;--------------------------------------------------------------------
  211. ;
  212. ;      DO_CHAR  SUBROUTINE
  213. ;
  214. ;      AL = character to write
  215. ;      DI = diplacement (address) of top row of pixels
  216. ;
  217. ;      Note: SI and ES are destroyed
  218. ;
  219. ;--------------------------------------------------------------------
  220. ;
  221. do_char:
  222.        push    ax
  223.        push    bx
  224.        push    cx
  225.        push    di
  226.        push    ds
  227. ;
  228. ;                      ; get scan pattern table pointer into BX
  229.        cmp     video_mode,herc_mode
  230.        je      herc_1
  231.        mov     bx,offset ibm_pattern
  232.                                ; IBM graphics mode - use appropriate table
  233.        jmp     c_1
  234. herc_1:        mov     bx,offset herc_pattern
  235.                                ; herc graphics mode - use appropriate table
  236. c_1:
  237. ;
  238. ;                      ; set up source address registers
  239.        xor     ah,ah           ; character to SI
  240.        mov     si,ax
  241. IFDEF iAPX286
  242.        shl     si,3            ; *8 for 8-byte table entry
  243. ELSE
  244.        shl     si,1            ; *8 for 8-byte table entry
  245.        shl     si,1
  246.        shl     si,1
  247. ENDIF
  248.                                ; next, find beginning of table
  249.        cmp     al,7Fh          ; ROM or user table?
  250.        jg      u_tbl
  251.                                ; ROM table
  252.        add     si,charbase     ; character table base added to offset
  253.        mov     ax,mpx_bios     ; BIOS code segment to DS
  254.        mov     ds,ax
  255.        jmp     c_2
  256. u_tbl:                         ; user table
  257.        xor     ax,ax           ; zero (interrupt vector) to DS
  258.        mov     ds,ax
  259.        mov     ax,si           ; save table offset in AX
  260.        assume  ds:intvec
  261.        lds     si,user_table   ; load DS:SI from interrupt vector
  262.        add     si,ax           ; add offset into table base
  263. c_2:
  264. ;
  265. ;                      ; set up destination address registers
  266.        mov     ax,pixbase      ; get display segment in ES
  267.        mov     es,ax
  268.                                ; displacement already in DI
  269. ;
  270. ;
  271. ;                      ; transfer the character
  272.        mov     ax,di           ; save top-row displacement in AX
  273.        mov     cx,8            ; transfer 8 rows
  274.        cld                     ; direction = up
  275. c_loop:        mov     di,ax           ; top-row displacement
  276.        add     di,cs:[bx]      ; add entry from scan-pattern table
  277.        movsb                   ; actually transfer a byte and bump SI & DI
  278.        add     bx,2            ; next entry in scan-pattern table
  279.        loop    c_loop
  280. ;
  281. ;                      ; if hercules mode, blank the extra rows
  282.        pop     ds              ; restore DS to Bios data
  283.        assume  ds:bios_data
  284.        cmp     video_mode,herc_mode
  285.        jne     c_3
  286.                                ; Hercules mode
  287.        mov     si,ax           ; don't need SI. Save top-row displacement
  288.        xor     ax,ax           ; zero AX
  289.        mov     cx,4            ; four rows to blank
  290.        cld
  291. c_blnk: mov    di,si           ; top-row displacement
  292.        add     di,cs:[bx]      ; add entry from scan-pattern table
  293.        stosb                   ; transfer a zero byte
  294.        add     bx,2            ; next entry in scan-pattern table
  295.        loop    c_blnk
  296. c_3:
  297. ;
  298. ;                      ; clean up and return
  299.        pop     di
  300.        pop     cx
  301.        pop     bx
  302.        pop     ax
  303.        ret
  304. page
  305. ;---------------------------------------------------------------------
  306. ;
  307. ;      DO_ATTRIB  SUBROUTINE
  308. ;
  309. ;      BL = attribute byte
  310. ;      DI = displacement (address) of top row of pixels
  311. ;      ES is destroyed
  312. ;
  313. ;      Because attributes don't "just happen" in graphics mode, here's
  314. ;      what we have to transform them to.
  315. ;
  316. ;      CODE    USUALLY MEANS           IBM MODE        HERC MODE
  317. ;      00      invisible               invisible       invisible
  318. ;      01      underline               [normal]        underline
  319. ;      07      normal                  normal          normal
  320. ;      0F      hi-intens               [rev video]     [rev video]
  321. ;      70      rev video               rev video       rev video
  322. ;
  323. ;      Anything else displays as normal
  324. ;      Note that there's no way to make blinking happen.
  325. ;
  326. ;-----------------------------------------------------------------------
  327. ;
  328. do_attrib:
  329.        assume  ds:bios_data
  330.        push    ax
  331.        mov     ax,pixbase      ; Display base to ES
  332.        mov     es,ax
  333.        pop     ax
  334. ;
  335. ;                      ; which attribute, if any?
  336.        and     bl,7Fh          ; mask off blink bit
  337.        cmp     bl,0            ; invisible?
  338.        je      invisible
  339.        cmp     bl,0Fh          ; reverse video? (instead of bright)
  340.        je      reverse
  341.        cmp     bl,70H          ; reverse video?
  342.        je      reverse
  343.        cmp     bl,01           ; underline?
  344.        je      underline
  345.        ret                     ; none of the above. Display normal.
  346. ;
  347. ;                      ; underline the character
  348. underline:
  349.        cmp     video_mode,herc_mode
  350.        je      ul_1
  351.        ret                     ; don't do it for IBM mode
  352. ul_1:  mov     byte ptr es:[di+40B4h],0FFh
  353.                                ; move ones to 11th line of pixel array
  354.                                ; 40B4h is the 11th entry in herc_pattern
  355.        ret
  356. ;
  357. ;                      ; make it invisible
  358. invisible:
  359.        push    ax
  360.        push    bx
  361.        push    cx
  362.        push    dx
  363.        xor     ax,ax           ; zero the AX
  364.        cmp     video_mode,herc_mode
  365.        je      herc_3
  366.        mov     bx,offset ibm_pattern
  367.                                ; point to scan pattern
  368.        jmp     inv_1
  369. herc_3:        mov     bx,offset herc_pattern
  370.                                ; point to scan pattern
  371. inv_1: mov     dx,di           ; save addr of top row of pixels in DX
  372.        mov     cx,8            ; 8 bytes to be moved
  373.        cld                     ; direction = up
  374. invis_loop:
  375.        mov     di,dx           ; top row address
  376.        add     di,cs:[bx]      ; add scan-table offset
  377.        stosb                   ; move a zero byte
  378.        add     bx,2            ; bump the scan-table pointer
  379.        loop    invis_loop
  380.        pop     dx
  381.        pop     cx
  382.        pop     bx
  383.        pop     ax
  384.        ret
  385. ;
  386. ;                      ; reverse video
  387. reverse:
  388.        push    bx
  389.        push    cx
  390.        push    dx
  391.        cmp     video_mode,herc_mode
  392.        je      herc_4
  393.        mov     bx,offset ibm_pattern
  394.                                ; point to scan pattern
  395.        mov     cx,8            ; 8 scan lines for IBM mode
  396.        jmp     rev_1
  397. herc_4:        mov     bx,offset herc_pattern
  398.                                ; point to scan pattern
  399.        mov     cx,12           ; 12 scan lines for Hercules mode
  400. rev_1: mov     dx,di           ; save addr of top row of pixels in DX
  401.        cld                     ; direction = up
  402. rev_loop:
  403.        mov     di,dx           ; top row address
  404.        add     di,cs:[bx]      ; add scan-table offset
  405.        not     es:byte ptr[di] ; invert one scan line
  406.        add     bx,2            ; bump the scan-table pointer
  407.        loop    rev_loop
  408.        pop     dx
  409.        pop     cx
  410.        pop     bx
  411.        ret
  412. page
  413. ;--------------------------------------------------------------
  414. ;
  415. ;      SUBROUTINE  FULL_SCREEN_SCROLL
  416. ;
  417. ;      This scrolls the entire screen up one print line (8 or 12 pixels).
  418. ;      Actually, we'll protect one line on the bottom (e.g.-function keys).
  419. ;
  420. ;-----------------------------------------------------------------
  421. ;
  422. ;                      ; A few constants, initialized by set_mode
  423. num_rows       db      ?       ; number of rows in display
  424.                                ;   = 42 (IBM)  or 28 (Herc)
  425. scr_start      dw      ?       ; 2*90 or 3*90 depending on mode
  426. scr_length     dw      ?       ; number of words to transfer in a sweep
  427.                                ;   = 41*start /2 = 3690        (IBM)
  428.                                ;   = 27*start /2 = 3645        (Herc)
  429. ;
  430. full_screen_scroll:
  431.        assume  ds:bios_data
  432.        push    ds
  433.        push    ax
  434.        push    cx
  435.        mov     ax,pixbase      ; start getting display segment
  436.        cmp     active_page,0   ; page 0?
  437.        je      scr_pg0
  438.        add     ax,800H         ; page 1. bump by half of 64K
  439. scr_pg0:
  440.        mov     ds,ax           ; save display segment in DS
  441.        mov     es,ax           ; ... and in ES
  442. ;
  443.        xor     ax,ax           ; zero AX
  444.        call    scr_shift
  445.        mov     ax,2000H        ; bump interlace counter
  446.        call    scr_shift
  447.        mov     ax,4000H
  448.        call    scr_shift
  449.        mov     ax,6000H
  450.        call    scr_shift
  451. ;
  452.        pop     cx
  453.        pop     ax
  454.        pop     ds
  455.        ret
  456. ;
  457. ;
  458. ; scr_shift does the actual work of scrolling, one set of interlace
  459. ;   lines at a time.
  460. ;
  461. scr_shift:
  462.        cld                     ; block moves will be UP
  463.        mov     di,ax           ; interlace scan ID to DI
  464.        mov     si,ax           ; ... and to SI
  465.        add     si,cs:scr_start
  466.                                ; but bump by "start"
  467.        mov     cx,cs:scr_length
  468.                                ; set counter for transfer
  469.        rep     movsw           ; and scroll a set of lines
  470.        xor     ax,ax           ; set up a zero word
  471.        mov     cx,cs:scr_start ; set counter for one more line
  472.        shr     cx,1            ; /2 for word transfers
  473.        rep     stosw           ; and blank the line
  474.        ret
  475. page
  476. ;-----------------------------------------------------------
  477. ;
  478. ;      SUBROUTINE FLASH
  479. ;
  480. ;      Flashes the screen inverse video and back to normal.
  481. ;      Used in place of an audible bell.
  482. ;
  483. ;-------------------------------------------------------------
  484. ;
  485. flash:
  486.        push    cx
  487.        push    di
  488.        push    es
  489. ;
  490.        mov     di,pixbase      ; get display area base
  491.        cmp     active_page,0   ; page 0?
  492.        je      pg0_f
  493.        add     di,800H         ; no, page 1
  494. pg0_f: mov     es,di           ; put resulting pointer to display in ES
  495. ;
  496. ;                      ; loop to invert screen
  497.        xor     di,di           ; point to beginning of display area
  498.        mov     cx,4000H        ; number of words to invert
  499. flash_loop_1:
  500.        not     word ptr es:[di]
  501.                                ; invert one location
  502.        add     di,2            ; bump location pointer a word
  503.        loop    flash_loop_1
  504. ;
  505. ;                      ; and invert it back to normal
  506.        xor     di,di           ; point to beginning of display area
  507.        mov     cx,4000H        ; number of words to invert
  508. flash_loop_2:
  509.        not     word ptr es:[di]
  510.                                ; invert one location
  511.        add     di,2            ; bump location pointer a word
  512.        loop    flash_loop_2
  513. ;
  514.        pop     es
  515.        pop     di
  516.        pop     cx
  517.        ret
  518. page
  519. ;*****************************************************
  520. ;*     Data areas for character handling
  521. ;*****************************************************
  522. ;
  523. pixels         db      12 dup(?)       ; 12 bytes for pixel pattern
  524. ibm_pattern    dw      0000h,2000h,4000h,6000h,005Ah,205Ah,405Ah,605Ah
  525. herc_pattern   dw      4000h,6000h,005Ah,205Ah,405Ah,605Ah,00B4h,20B4h
  526. blank_pattern  dw      0000h,2000h,40B4h,60B4h
  527. ;
  528. ;
  529. cseg   ends
  530.        end
  531.